package se.webbzon.boltzmann.effect;

import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;

public class ShakeEffect implements Effect {
	
	// The default duration of this shake effect
	private static final int defaultDuration = 30;
	
	// The duration of this shake effect
	private final int duration;
	
	// The instance to shake
	private final WorldStaticObject parent;
	
	// The shaker instance
	private final Shaker shaker;
	
	// The original size and position of the instance
	private final Point3d originalPosition;
	private final Vector3d originalSize;
	
	// The remaining time of this shake effect
	private int remaining;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public ShakeEffect(WorldStaticObject parent) {
		this(parent,defaultDuration);
	}

	public ShakeEffect(WorldStaticObject parent, int duration) {
		this.duration = duration;
		this.parent = parent;
		shaker = new Shaker();
		originalPosition = new Point3d();
		originalSize = new Vector3d();
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override public void launch(WorldArea world) {
		world.createInstance(shaker);
		parent.getSize(originalSize);
		parent.getPosition(originalPosition);
	}

	@Override public void terminate(WorldArea world) {
		world.destroyInstance(shaker);
		final Point3d p = originalPosition;
		parent.setPosition(p.getX(), p.getY(), p.getZ());
		final Vector3d s = originalSize;
		parent.setSize(s.getX(), s.getY(), s.getZ());
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class Shaker extends WorldObject {

		public Shaker() {
			super(WorldObject.onCreate + WorldObject.onStep);
		}
		
		@Override public void onCreate(WorldArea world) {
			remaining = duration;
		}

		@Override public void onStep(WorldArea world) {
			if (remaining > 0) {
				final double p = remaining / (double) duration;
				final double amp = p * 0.2 * Math.sin(3 * Math.PI * p * p);
				final Point3d pos = originalPosition;
				final Vector3d size = originalSize;
				parent.setSize(	(1 + amp) * size.getX(), 
								(1 - amp) * size.getY(), 
								(1 + amp) * size.getZ());
				parent.setPosition(	pos.getX(), 
									pos.getY() + (parent.getHeight() - size.getY()) / 2, 
									pos.getZ());
				remaining--;
			} else if (remaining == 0)
				terminate(world);
		}
		
	}

}
